package com.nikkerball.converter;

import com.nikkerball.Computation;
import com.nikkerball.unit.Legend;
import com.nikkerball.unit.Unit;

import java.math.BigDecimal;
import java.util.Properties;

/**
 * User: Marius
 * Date: 14-Feb-2010
 * Time: 12:44:34
 * <p/>
 * Represents a Conversion between two units for a value
 */
public class Conversion implements Computation {

    // ----- instance fields -----

    private Unit fromUnit;

    private BigDecimal fromValue;

    private Legend legend;

    private Unit toUnit;

    private BigDecimal toValue;

    // ----- constructors -----

    public Conversion(Unit fromUnit, Unit toUnit, BigDecimal fromValue) {
        this.fromUnit = fromUnit;
        this.toUnit = toUnit;
        this.fromValue = fromValue;
        calculateToValue();
        calculateConversionLegend();
    }

    // ----- Computation -----

    public String getDescription(Properties labels) {
        StringBuilder description = new StringBuilder();

        description.append(getFromValue().toString()).append(" ")
                .append(labels.getProperty(getFromUnit().getKey(), getFromUnit().getKey()))
                .append(" = ").append(getLegend()).append(" ")
                .append(getToValue().toString()).append(" ")
                .append(labels.getProperty(getToUnit().getKey(), getToUnit().getKey()));

        return description.toString();
    }

    // ----- public methods -----

    public Unit getFromUnit() {
        return fromUnit;
    }

    public BigDecimal getFromValue() {
        return fromValue;
    }

    public Legend getLegend() {
        return legend;
    }

    public Unit getToUnit() {
        return toUnit;
    }

    public BigDecimal getToValue() {
        return toValue;
    }

    // ----------

    private void calculateConversionLegend() {
        if (toUnit.equals(fromUnit)) {
            legend = Legend.exactly;
        } else if (Legend.approximately.equals(fromUnit.getConversionLegend()) || Legend.approximately
                .equals(toUnit.getConversionLegend())) {
            // If at least one of the conversion units has approximately as Legend then the result is approximately
            legend = Legend.approximately;
        } else {
            // Neither or the two units are approximately - so the result is exactly
            legend = Legend.exactly;
        }
    }

    private void calculateToValue() {
        // Convert to the Base Unit First
        double baseConversion = fromValue.doubleValue() * fromUnit.getConversion().doubleValue();
        // Now Convert to the "to Unit"
        toValue = new BigDecimal(baseConversion / toUnit.getConversion().doubleValue());
    }
}


